package com.ncu.xrpc.handler;

import cn.hutool.core.util.StrUtil;
import com.ncu.xrpc.entity.XRpcRequest;
import com.ncu.xrpc.entity.XRpcResponse;
import com.ncu.xrpc.util.HessianUtil;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: xiongwb
 * Date: 2021/9/11 19:17
 * Describe: RPC服务端处理器(基于netty)
 */
@Slf4j
public class RpcServerHandler extends SimpleChannelInboundHandler {

    private final Map<String, Object> handlerMap;

    /**
     * 接收的消息
     */
    private XRpcRequest xRpcRequest;



    /**
     * @param handlerMap 从RpcServer中传过来，也就是说和RpcServer共用一个handlerMap
     */
    public RpcServerHandler(Map<String, Object> handlerMap){
        this.handlerMap = handlerMap;
    }

    /**
     * @param channelHandlerContext
     * @param msg 网络中传输的字节数组
     * @throws Exception
     * Describe: 进行收发消息（消息基于Hessian序列化）
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
        byte[] msg1 = (byte[]) msg;
        System.out.println("size:"+msg1.length);
        //将消息进行反序列化
        xRpcRequest = (XRpcRequest) HessianUtil.deserialize((byte[])msg);

        //创建并初始化响应对象
        XRpcResponse xRpcResponse = new XRpcResponse(xRpcRequest.getRequestId());

        try{
            //拿到方法执行后的结果
            Object result = handle(xRpcRequest);

            //将方法执行完的结果放到response中
            xRpcResponse.setResult(result);
        }catch (Exception e){
            log.error("handle failure",e);
            //将异常信息放到response
            xRpcResponse.setError(e.getMessage());
        }

        //将对象进行序列化
        byte[] serialize = HessianUtil.serialize(xRpcResponse);

        //将响应写回,并且监听关闭
        channelHandlerContext.writeAndFlush(serialize).addListener(ChannelFutureListener.CLOSE);
    }

    /**
     * @param xRpcRequest
     * @return  方法调用后的返回结果
     * @throws InvocationTargetException
     */
    private Object handle(XRpcRequest xRpcRequest) throws InvocationTargetException {
        //服务名
        String serviceName = xRpcRequest.getClassName();

        //获取版本号
        String version = xRpcRequest.getVersion();

        //拼接完整服务名
        if(StrUtil.isNotEmpty(version)){
            serviceName = serviceName +"-"+version;
        }

        if(!handlerMap.containsKey(serviceName)){
            throw new RuntimeException("can not find serviceBean by key:"+serviceName);
        }
        Object serviceBean = handlerMap.get(serviceName);

        Class<?> serviceBeanClass = serviceBean.getClass();

        //调用的方法名
        String methodName = xRpcRequest.getMethodName();

        //调用的方法的参数类型
        Class<?>[] parameterTypes = xRpcRequest.getParameterTypes();

        //调用方法的参数的参数值
        Object[] args = xRpcRequest.getArgs();

        //拿到代理对象
        FastClass serviceBeanFastClass = FastClass.create(serviceBeanClass);

        //拿到代理方法
        FastMethod serviceBeanMethod = serviceBeanFastClass.getMethod(methodName, parameterTypes);

        //执行代理方法并返回执行的结果
        return serviceBeanMethod.invoke(serviceBean, args);
    }
}
